<?php declare(strict_types=1);

/**
 * @author      guosir
 * @copyright   2023-2025 owner
 **/

namespace Srv\Apps\Apis\Promotion\Ctl;

use Srv\Apps\Apis\Skit\Ctl\SkitInfoCtl;
use Srv\Apps\Apis\Skit\Ctl\SkitSeriesCtl;
use Srv\Apps\Proto\DTO\Promotion\PutLinkAddDTO;
use Srv\Apps\Proto\DTO\Promotion\PutLinkEditDTO;
use Srv\Apps\Proto\DTO\Promotion\PutLinkListDTO;
use Srv\Apps\Proto\Enum\PutLinkPlatformEnum;
use Srv\Apps\Proto\VO\Promotion\PutLinkListVO;
use Srv\Apps\Proto\VO\Promotion\PutLinkVO;
use Srv\Apps\Proto\VO\Skit\SkitInfoVO;
use Srv\Apps\Proto\VO\Skit\SkitSeriesVO;
use Srv\Libs\Common\CommArray;
use Srv\Libs\Common\CommString;
use Srv\Libs\Common\CommTime;
use Srv\Libs\Frame\ControllerAbstract;
use Srv\Libs\Frame\Page;
use Srv\Libs\Storage\DataMysql;

final class PutLinkCtl extends ControllerAbstract
{
    private ?DataMysql $DbAuto              = null;     // DB-Write
    private string $putLinkUrl              = 'https://wwwxc.nilela.com/episode/{KEY}';                 // 投放地址
    private string $putLinkOneUrl           = 'https://wwwxc.nilela.com/promo/{KEY}';                   // 投放地址一
    private string $putLinkTwoUrl           = 'https://wwwxc.nilela.com/tohome/{KEY}';                  // 投放地址二
    private string $putLinkSkitUrl          = 'https://wwwxc.nilela.com/play/{SKIT_KEY}';               // FB深链剧(iOS)
    private string $putLinkSeriesUrl        = 'https://wwwxc.nilela.com/play/{SKIT_KEY}/{SERIES_KEY}';  // FB深链集(iOS)



    /**
     * @return static
     * tag
     */
    final public static function tag():self
    {
        $thisObject                         = self::tagGet();
        if($thisObject instanceof self){
            $thisObject->DbAuto             = self::getDbAuto();
        }
        if($thisObject->isRelease()){
            $thisObject->putLinkUrl         = "https://www.xc.com/episode/{KEY}";
            $thisObject->putLinkOneUrl      = "https://www.xc.com/promo/{KEY}";
            $thisObject->putLinkTwoUrl      = "https://www.xc.com/tohome/{KEY}";
            $thisObject->putLinkSkitUrl     = 'https://www.xc.com/play/{SKIT_KEY}';
            $thisObject->putLinkSeriesUrl   = 'https://www.xc.com/play/{SKIT_KEY}/{SERIES_KEY}';
        }
        return $thisObject;
    }

    /**
     * @param int $ptlrId
     * @return array
     * getPutLinkSrc
     */
    public function getPutLinkSrc(int $ptlrId):array
    {
        if($ptlrId < 1) return [];
        $isFail     = false;
        $info       = $this->DbAuto->getDataOne('SELECT ptlr_id, ptlr_key, ptlr_name, ptlr_platform, ptlr_ad_id, skio_id, skss_id, ptlr_delete, ptlr_create_time, ptlr_update_time FROM '.$this->DbAuto->getTableNameAll('put_link_record').' WHERE ptlr_id='.$ptlrId.' AND ptlr_delete=0', $isFail);
        if($isFail || !isset($info['ptlr_id'])) return [];
        return $info;
    }

    /**
     * @param Page $Page
     * @param array $whereData
     * @return PutLinkListVO|null
     * getPutLinkList
     */
    public function getPutLinkList(Page $Page, array $whereData): ?PutLinkListVO
    {
        $limitString            = $Page->getLimitString();
        $whereString            = ' WHERE ptlr_delete=0 ';
        // 检索条件
        if(count($whereData) > 0)foreach ($whereData as $key => $val){
            switch ($key){
                case PutLinkListDTO::_ptlrId:
                    $whereString    .= (strlen($whereString)>0?' AND ':'').'ptlr_id='. intval($val);
                    break;
                case PutLinkListDTO::_name:
                    $whereString    .= (strlen($whereString)>0?' AND ':'').'ptlr_name LIKE \'%'.$this->DbAuto->getRealEscapeString($val).'%\'';
                    break;
                case PutLinkListDTO::_key:
                    $whereString    .= (strlen($whereString)>0?' AND ':'').'ptlr_key LIKE \''.$this->DbAuto->getRealEscapeString($val).'%\'';
                    break;
                case PutLinkListDTO::_adId:
                    $whereString    .= (strlen($whereString)>0?' AND ':'').'ptlr_ad_id LIKE \''.$this->DbAuto->getRealEscapeString($val).'%\'';
                    break;
                case PutLinkListDTO::_platform:
                    $whereString    .= (strlen($whereString)>0?' AND ':'').'ptlr_platform='. intval($val);
                    break;
            }
        }
        $isFail                 = false;
        $sql                    = 'SELECT SQL_CALC_FOUND_ROWS ptlr_id, ptlr_key, ptlr_name, ptlr_platform, ptlr_ad_id, skio_id, skss_id, ptlr_delete, ptlr_create_time, ptlr_update_time FROM '.$this->DbAuto->getTableNameAll('put_link_record').$whereString.' ORDER BY ptlr_id DESC '.$limitString;
        $list                   = $this->DbAuto->getData($sql, $isFail);
        $totalNum               = $this->DbAuto->getDataInt('SELECT FOUND_ROWS() as num', 'num');
        if($isFail) return null;
        $PutLinkVOList          = [];
        if(CommArray::isForeach($list)){
            $skioIdList         = array_map('intval', array_unique(array_column($list, 'skio_id')));
            $SkitInfoVOList     = SkitInfoCtl::tag()->getSkitInfoBatch($skioIdList);
            $skssIdList         = array_map('intval', array_unique(array_column($list, 'skss_id')));
            $SkitSeriesVOList   = SkitSeriesCtl::tag()->getSkitSeriesInfoBatch($skssIdList);
            foreach($list as $info){
                $ptlrIdItem         = intval($info['ptlr_id']??0);
                if($ptlrIdItem < 1) continue;
                $PutLinkVO          = $this->getPutLinkVO($info);
                if(!($PutLinkVO instanceof PutLinkVO)) continue;
                $skioIdItem         = intval($info['skio_id']);
                $skssIdItem         = intval($info['skss_id']);
                $SkitInfoVO         = $SkitInfoVOList[$skioIdItem]??null;
                if($SkitInfoVO instanceof SkitInfoVO) {
                    $PutLinkVO->setSkitInfo($SkitInfoVO);
                    $PutLinkVO->setUrlSkit(str_replace('{SKIT_KEY}', $SkitInfoVO->getKey(), $this->putLinkSkitUrl));
                }
                $SkitSeriesVO       = $SkitSeriesVOList[$skssIdItem]??null;
                if($SkitSeriesVO instanceof SkitSeriesVO){
                    $PutLinkVO->setSkitSeries($SkitSeriesVO);
                    $seriesUrl      = str_replace('{SKIT_KEY}', $SkitInfoVO->getKey(), $this->putLinkSeriesUrl);
                    $seriesUrl      = str_replace('{SERIES_KEY}', $SkitSeriesVO->getKey(), $seriesUrl);
                    $PutLinkVO->setUrlSeries($seriesUrl);
                }
                $PutLinkVOList[]    = $PutLinkVO;
            }
        }
        $PutLinkListVO        = new PutLinkListVO();
        $PutLinkListVO->setList($PutLinkVOList);
        $PutLinkListVO->setPage($Page->getPageVO($totalNum));
        return $PutLinkListVO;
    }

    /**
     * @param int $ptlrId
     * @return PutLinkVO|null
     * getPutLinkInfo
     */
    public function getPutLinkInfo(int $ptlrId):?PutLinkVO
    {
        $infoSrc    = $this->getPutLinkSrc($ptlrId);
        if(!isset($infoSrc['ptlr_id'])) return null;
        return $this->getPutLinkVO($infoSrc);
    }

    /**
     * @param array $info
     * @return PutLinkVO|null
     * getPutLinkVO
     */
    public function getPutLinkVO(array $info):?PutLinkVO
    {
        $ptlrId             = intval($info['ptlr_id']??0);
        if($ptlrId < 1) return null;
        $PutLinkVO      = new PutLinkVO();
        $PutLinkVO->setPtlrId($ptlrId);
        $PutLinkVO->setName(trim($info['ptlr_name']));
        $PutLinkVO->setPlatform(PutLinkPlatformEnum::parseValue($info['ptlr_platform']));
        $PutLinkVO->setKey(trim($info['ptlr_key']));
        $PutLinkVO->setAdId(trim($info['ptlr_ad_id']));
        $PutLinkVO->setSkioId(intval($info['skio_id']));
        $PutLinkVO->setSkssId(intval($info['skss_id']));
        $PutLinkVO->setCreateTime(intval($info['ptlr_create_time']));
        $PutLinkVO->setUpdateTime(intval($info['ptlr_update_time']));
        $PutLinkVO->setUrl(str_replace('{KEY}', $PutLinkVO->getKey(), $this->putLinkUrl));
        $PutLinkVO->setUrlOne(str_replace('{KEY}', $PutLinkVO->getKey(), $this->putLinkOneUrl));
        $PutLinkVO->setUrlTwo(str_replace('{KEY}', $PutLinkVO->getKey(), $this->putLinkTwoUrl));
        return $PutLinkVO;
    }

    /**
     * @param array $setData
     * @return int
     * putLinkAdd
     */
    public function putLinkAdd(array $setData):int
    {
        if(count($setData) < 1) return 0;
        $setString      = '';
        foreach ($setData as $key => $val){
            switch ($key){
                case PutLinkAddDTO::_skioId:
                    $skioId         = intval($val);
                    $skitInfoSrc    = SkitInfoCtl::tag()->getSkitInfoSrc($skioId);
                    if(!isset($skitInfoSrc['skio_id'])) return 0;
                    $setString      .= (strlen($setString) > 0 ? ', ' : '') . 'skio_id='.$skioId;
                    break;
                case PutLinkAddDTO::_skssId:
                    $skssId         = intval($val);
                    $skitSeriesSrc  = SkitSeriesCtl::tag()->getSkitSeriesSrc($skssId);
                    if(!isset($skitSeriesSrc['skss_id'])) return 0;
                    $setString      .= (strlen($setString) > 0 ? ', ' : '') . 'skss_id='.$skssId;
                    break;
                case PutLinkAddDTO::_name:
                    $setString      .= (strlen($setString) > 0 ? ', ' : '') . 'ptlr_name=\''.$this->DbAuto->getRealEscapeString($val).'\'';
                    break;
                case PutLinkAddDTO::_platform:
                    $setString      .= (strlen($setString) > 0 ? ', ' : '') . 'ptlr_platform='. intval($val);
                    break;
                case PutLinkAddDTO::_adId:
                    $setString      .= (strlen($setString) > 0 ? ', ' : '') . 'ptlr_ad_id=\''.$this->DbAuto->getRealEscapeString($val).'\'';
                    break;
            }
        }
        if(strlen($setString) < 1)  return 0;
        $currTime   = CommTime::getTimeStamp(0);
        $randkey    = $this->getPutLinkKey();
        $isFail     = false;
        $sql        = 'INSERT INTO '.$this->DbAuto->getTableNameAll('put_link_record').' SET '.$setString.', ptlr_key=\''.$this->DbAuto->getRealEscapeString($randkey).'\', ptlr_delete=0, ptlr_create_time='.$currTime.', ptlr_update_time='.$currTime;
        $ptlrId     = $this->DbAuto->getDataId($sql, $isFail);
        if($isFail || $ptlrId < 1) return 0;
        return $ptlrId;
    }

    /**
     * @param int $ptlrId
     * @param array $setData
     * @return bool
     * putLinkEdit
     */
    public function putLinkEdit(int $ptlrId, array $setData):bool
    {
        if($ptlrId < 1 || count($setData) < 1) return false;
        $setString      = '';
        foreach ($setData as $key => $val){
            switch ($key){
                case PutLinkEditDTO::_name:
                    $setString      .= (strlen($setString) > 0 ? ', ' : '') . 'ptlr_name=\''.$this->DbAuto->getRealEscapeString($val).'\'';
                    break;
                case PutLinkEditDTO::_platform:
                    $setString      .= (strlen($setString) > 0 ? ', ' : '') . 'ptlr_platform='. intval($val);
                    break;
                case PutLinkEditDTO::_adId:
                    $setString      .= (strlen($setString) > 0 ? ', ' : '') . 'ptlr_ad_id=\''.$this->DbAuto->getRealEscapeString($val).'\'';
                    break;
                case PutLinkEditDTO::_skioId:
                    $skioId         = intval($val);
                    $skitInfoSrc    = SkitInfoCtl::tag()->getSkitInfoSrc($skioId);
                    if(!isset($skitInfoSrc['skio_id'])) return false;
                    $setString      .= (strlen($setString) > 0 ? ', ' : '') . 'skio_id='.$skioId;
                    break;
                case PutLinkEditDTO::_skssId:
                    $skssId         = intval($val);
                    $skitSeriesSrc  = SkitSeriesCtl::tag()->getSkitSeriesSrc($skssId);
                    if(!isset($skitSeriesSrc['skss_id'])) return false;
                    $setString      .= (strlen($setString) > 0 ? ', ' : '') . 'skss_id='.$skssId;
                    break;
            }
        }
        if(strlen($setString) < 1) return false;
        $isFail     = false;
        $currTime   = CommTime::getTimeStamp(0);
        $sql        = 'UPDATE '.$this->DbAuto->getTableNameAll('put_link_record').' SET '.$setString.', ptlr_update_time='.$currTime.' WHERE ptlr_id='.$ptlrId.' AND ptlr_delete=0';
        if($this->DbAuto->getDataNum($sql, $isFail) < 1 || $isFail) return false;
        return true;
    }

    /**
     * @return string
     * getPutLinkKey
     */
    public function getPutLinkKey():string
    {
        $minLength          = 8;        // 最小长度
        $maxLength          = 16;       // 最大长度
        $maxNum             = 200;
        $currNum            = 1;
        $indexNum           = 1;
        $randKey            = strtolower(CommString::genRandStr($minLength));
        while($currNum <= $maxNum){
            $idFind         = $this->DbAuto->getDataInt('SELECT ptlr_id FROM '.$this->DbAuto->getTableNameAll('put_link_record').' WHERE binary ptlr_key=\''.$this->DbAuto->getRealEscapeString($randKey).'\'', 'ptlr_id');
            if($idFind < 1) break;
            if($indexNum >= 50){                // 失败自增长度1
                $indexNum   = 0;
                $minLength  += 1;
            }
            if($minLength > $maxLength) break;  // 长度封顶
            $randKey        = strtolower(CommString::genRandStr($minLength));
            ++$indexNum;
            ++$currNum;
        }
        return $randKey;
    }
}